# -*- coding: utf-8 -*-
#
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

"""函数调用发射器 - 迁移自IRCall.render方法"""


from mcpy.ir.expressions import IRCall
from mcpy.ir.expressions.access import IRAttribute
from mcpy.ir.expressions.basic import IRName
from mcpy.ir.expressions.lambda_expr import IRLambda
from mcpy.symbol_registry import get_global_registry
from mcpy.symbol_meta import SymbolKind, TypeKind
from ..core.emitter import EmitResult, NodeTypeEmitter
from ..core.context import CodeGenContext
from ..configs.operators import get_operator_precedence
from ..core.generator import get_global_generator
from .template_emitter import TemplateEmitter
from mcpy.type_system import get_cpp_type
from mcpy.ir.declarations import IRFunctionNode
from ...type_system import parse_type_with_context
from mcpy.codegen.utils.type_conversion import apply_variant_conversion
from mcpy.type_system import parse_type, is_protocol_type


class CallEmitter(NodeTypeEmitter):
    """处理函数调用的发射器

    - 普通函数调用：func(args)
    - 成员方法调用：obj.method(args) 或 obj->method(args)
    - 静态方法调用：Class::method(args)
    - 命名空间函数调用：namespace::function(args)
    """

    def __init__(self):
        super().__init__([IRCall])

    def _contains_comma_outside_string(self, arg_code: str) -> bool:
        """检查代码中是否包含字符串字面量外的逗号

        Args:
            arg_code: 参数代码字符串

        Returns:
            如果包含字符串外的逗号返回 True
        """
        if "," not in arg_code:
            return False

        in_string = False
        escape_next = False
        for char in arg_code:
            if escape_next:
                escape_next = False
                continue
            if char == "\\":
                escape_next = True
                continue
            if char == '"':
                in_string = not in_string
                continue
            if char == "," and not in_string:
                return True
        return False

    def _is_arrow_operator(self, arg_code: str, pos: int) -> bool:
        """检查指定位置是否是箭头操作符 -> 的一部分

        Args:
            arg_code: 参数代码字符串
            pos: 字符位置（通常是 '<' 或 '>' 的位置）

        Returns:
            如果是指箭头操作符的一部分返回 True
        """
        if pos == 0:
            return False
        # 检查前面是否是 '-'
        if arg_code[pos - 1] == "-":
            return True
        # 对于 '>'，检查后面是否是标识符字符（如 this->_x）
        if pos > 0 and arg_code[pos] == ">":
            if pos + 1 < len(arg_code):
                next_char = arg_code[pos + 1]
                if next_char.isalnum() or next_char == "_":
                    return True
        return False

    def _contains_template_or_comparison_ops(self, arg_code: str) -> bool:
        """检查代码中是否包含模板语法或比较运算符（排除箭头操作符）

        Args:
            arg_code: 参数代码字符串

        Returns:
            如果包含需要保护的尖括号返回 True
        """
        for i, char in enumerate(arg_code):
            if char == "<" and not self._is_arrow_operator(arg_code, i):
                return True
            elif char == ">" and not self._is_arrow_operator(arg_code, i):
                return True
        return False

    def _contains_logical_operators(self, arg_code: str) -> bool:
        """检查代码中是否包含逻辑运算符

        Args:
            arg_code: 参数代码字符串

        Returns:
            如果包含逻辑运算符返回 True
        """
        return "&&" in arg_code or "||" in arg_code

    def _is_properly_parenthesized(self, arg_code: str) -> bool:
        """检查代码是否已经用括号正确包裹

        Args:
            arg_code: 参数代码字符串

        Returns:
            如果已经正确包裹返回 True
        """
        if not arg_code.startswith("(") or not arg_code.endswith(")"):
            return False

        # 检查括号是否匹配
        paren_count = 0
        for char in arg_code:
            if char == "(":
                paren_count += 1
            elif char == ")":
                paren_count -= 1
                if paren_count < 0:
                    return False
        return paren_count == 0

    def _needs_macro_protection(self, arg_code: str) -> bool:
        """判断代码是否需要宏参数保护

        Args:
            arg_code: 参数代码字符串

        Returns:
            如果需要保护返回 True
        """
        return (
            self._contains_comma_outside_string(arg_code)
            or self._contains_template_or_comparison_ops(arg_code)
            or self._contains_logical_operators(arg_code)
        )

    def _protect_macro_arg(self, arg_code: str) -> str:
        """保护宏参数代码，如果包含特殊字符（如逗号、尖括号）则用括号包裹

        Args:
            arg_code: 参数代码字符串

        Returns:
            保护后的参数代码
        """
        if not self._needs_macro_protection(arg_code):
            return arg_code

        # 如果已经用括号正确包裹，检查是否需要额外保护
        if self._is_properly_parenthesized(arg_code):
            # 已经包裹，但包含特殊字符，保留原样（不再额外包裹）
            if self._contains_comma_outside_string(
                arg_code
            ) or self._contains_template_or_comparison_ops(arg_code):
                return arg_code

        return f"({arg_code})"

    def _generate_function_call_code(
        self,
        func_code: str,
        args: list[str],
        is_macro: bool = False,
    ) -> str:
        """生成函数调用代码

        统一的函数调用代码生成函数，支持宏参数保护

        Args:
            func_code: 函数名或函数表达式代码
            args: 参数代码列表
            is_macro: 是否为 C++ 宏（需要参数保护）

        Returns:
            生成的函数调用代码
        """
        if is_macro:
            # 对宏的参数进行保护
            protected_args = [self._protect_macro_arg(arg) for arg in args]
            args_list = ", ".join(protected_args)
        else:
            args_list = ", ".join(args)

        if len(args) == 0:
            return f"{func_code}()"
        else:
            return f"{func_code}({args_list})"

    def _is_function_macro(self, node: IRCall, context: CodeGenContext) -> bool:
        """检查函数调用是否是 C++ 宏

        Args:
            node: 函数调用节点
            context: 代码生成上下文

        Returns:
            是否为宏
        """
        # 先尝试从缓存的符号中获取（性能优化）
        if isinstance(node.func, IRName):
            cached_symbol = node.func.get_extension_param("symbol")
            if cached_symbol and cached_symbol.signatures:
                signature = cached_symbol.signatures[0]
                return getattr(signature, "is_macro", False)

        # 从符号中查找函数签名
        symbol = None
        func_name = None

        if isinstance(node.func, IRName):
            # 普通函数调用
            func_name = node.func.id
            if context.current_node:
                symbol = context.current_node.lookup_symbol(func_name)
        elif isinstance(node.func, IRAttribute):
            # 成员调用或命名空间调用
            if isinstance(node.func.value, IRName):
                # 命名空间调用：namespace.func (如 gtest.EXPECT_EQ)
                func_name = node.func.attr
                if context.current_node:
                    # 尝试查找导入的函数符号
                    symbol = context.current_node.lookup_symbol(func_name)
            # 成员调用（obj.method）通常不是宏，跳过检查

        if symbol and symbol.signatures:
            # 检查第一个签名的 is_macro 标志
            signature = symbol.signatures[0]
            return getattr(signature, "is_macro", False)

        return False

    def emit(self, node: IRCall, context: CodeGenContext) -> EmitResult:
        """生成函数调用代码

        迁移自IRCall.render方法的逻辑
        """
        # 检查是否是成员方法调用
        if isinstance(node.func, IRAttribute):
            # 检查是否是命名空间函数调用
            if isinstance(node.func.value, IRName) and self._is_module_with_namespace(
                node.func.value.id, context
            ):
                return self._emit_namespace_call(node, context)
            else:
                return self._emit_member_call(node, context)
        else:
            return self._emit_function_call(node, context)

    def _emit_function_call(self, node: IRCall, context: CodeGenContext) -> EmitResult:
        """渲染普通函数调用"""

        generator = get_global_generator()

        # 生成参数列表
        args = self._render_args(node, context)

        # 优先检查是否是简单嵌套函数调用（无捕获）
        # 必须在其他检查之前，因为简单嵌套函数应该直接生成临时对象调用
        # 但是，如果有默认参数且调用时参数不足，需要使用 mcpy::call 来处理
        simple_functor_name = self._get_simple_nested_function_functor_name(
            node, context
        )
        if simple_functor_name:
            # 检查是否需要使用默认参数
            if self._needs_default_params_for_nested_function(node, context):
                # 需要默认参数，不走临时对象调用路径，继续后续处理
                simple_functor_name = ""
            else:
                # 简单嵌套函数：生成临时对象调用 functor_name{}(args)
                if len(args) == 0:
                    code = f"{simple_functor_name}{{}}()"
                else:
                    args_list = ", ".join(args)
                    code = f"{simple_functor_name}{{}}({args_list})"
                return EmitResult(code=code, precedence=get_operator_precedence("call"))

        # 生成函数名（用于其他路径）
        func_code = generator.generate_expression(node.func, context)

        # 检查是否是栈 lambda 调用（直接调用 operator()，零开销）
        if self._is_stack_lambda_call(node, context):
            # 栈 lambda 调用：直接调用 operator()（强类型，零开销）
            args_list = ", ".join(args)
            code = f"{func_code}({args_list})"
        # 检查是否是可调用对象调用（lambda、函数指针等存储在 variant 中）
        elif self._is_callable_variant_call(node, context):
            # 检查是否是async函数调用（返回mc::result<T>）
            expected_cpp_type = node.get_extension_param("expected_return_cpp_type")
            if expected_cpp_type and expected_cpp_type.startswith("mc::result<"):
                # 使用call_async专门处理async函数调用
                # 提取result的值类型: mc::result<int> -> int
                import re

                match = re.match(r"mc::result<(.+)>", expected_cpp_type)
                if match:
                    value_type = match.group(1)
                    if len(args) == 0:
                        code = f"mcpy::call_async<{value_type}>({func_code})"
                    else:
                        args_list = ", ".join(args)
                        code = (
                            f"mcpy::call_async<{value_type}>({func_code}, {args_list})"
                        )
                else:
                    # 无法解析，使用普通call
                    code = f"mcpy::call({func_code})"
            else:
                # 可调用对象调用：使用统一的 mcpy::call 接口（可变模板）
                # 根据期望返回类型生成强类型或弱类型调用
                call_template_arg = self._get_call_return_type(node, context)

                if len(args) == 0:
                    code = f"mcpy::call{call_template_arg}({func_code})"
                else:
                    # 直接传递参数，mcpy::call 会自动包装为 mc::variants
                    args_list = ", ".join(args)
                    code = f"mcpy::call{call_template_arg}({func_code}, {args_list})"
        else:
            # 普通函数调用
            # 先尝试使用模板系统（用于有@mcpy_emit_template注解的函数）
            template_emitter = TemplateEmitter()
            template_result = template_emitter.emit(node, context)
            if template_result:  # 如果有emit_template，使用其结果
                return template_result

            # 检查是否是全局异步函数 struct
            # 如果是，则生成 struct_name{}(args) 形式
            # 首先检查扩展参数中是否已经设置了 struct 名称（用于包装函数调用原异步函数）
            global_async_struct_name = node.get_extension_param(
                "_global_async_struct_name"
            )
            if not global_async_struct_name:
                global_async_struct_name = self._get_global_async_struct_name(
                    node, context
                )
            if global_async_struct_name:
                if len(args) == 0:
                    code = f"{global_async_struct_name}{{}}()"
                else:
                    # 异步函数 struct 不是宏，不需要参数保护
                    # 生成 struct_name{}(args) 形式，不需要外层括号
                    code = self._generate_function_call_code(
                        f"{global_async_struct_name}{{}}", args, False
                    )
            else:
                # 检查是否是模板函数调用（需要显式模板参数）
                template_args = self._get_explicit_template_args(node, context)
                if template_args:
                    # 对于模板函数，先构造带模板参数的函数名
                    func_with_template = f"{func_code}<{template_args}>"
                    # 检查是否为宏
                    is_macro = self._is_function_macro(node, context)
                    code = self._generate_function_call_code(
                        func_with_template, args, is_macro
                    )
                else:
                    # 检查是否为宏
                    is_macro = self._is_function_macro(node, context)
                    code = self._generate_function_call_code(func_code, args, is_macro)

        return EmitResult(code=code, precedence=get_operator_precedence("call"))

    def _emit_member_call(self, node: IRCall, context: CodeGenContext) -> EmitResult:
        """渲染成员方法调用"""

        if not isinstance(node.func, IRAttribute):
            raise ValueError("Expected IRAttribute for member call")

        # 先尝试使用模板系统（用于 list.pop、list.append 等内置方法）
        template_emitter = TemplateEmitter()
        template_result = template_emitter.emit(node, context)
        if template_result:  # 如果模板系统处理了（有模板或回调），使用其结果
            return template_result
        # 如果返回 None，说明没有模板，继续用常规逻辑处理（如静态方法调用）

        generator = get_global_generator()

        # 生成对象代码
        obj_code = generator.generate_expression(node.func.value, context)
        method_name = node.func.attr

        # 处理this指针
        if obj_code in ("self", "this"):
            obj_code = "this"

        # 生成参数列表
        method_args = self._render_args(node, context)

        # 检查是否为静态方法调用
        if isinstance(node.func.value, IRName) and self._is_static_member(
            node.func.value.id, node.func.attr, context
        ):
            # 静态方法调用：Class::static_method(args)
            func_code = f"{obj_code}::{method_name}"
            is_macro = self._is_function_macro(node, context)
            code = self._generate_function_call_code(func_code, method_args, is_macro)
        else:
            # 实例方法调用：根据对象类型决定使用 . 还是 ->
            use_pointer_op = self._is_object_pointer_type(node)
            operator = "->" if use_pointer_op else "."
            func_code = f"{obj_code}{operator}{method_name}"
            is_macro = self._is_function_macro(node, context)
            code = self._generate_function_call_code(func_code, method_args, is_macro)

        return EmitResult(code=code, precedence=get_operator_precedence("call"))

    def _emit_namespace_call(self, node: IRCall, context: CodeGenContext) -> EmitResult:
        """渲染命名空间函数调用"""
        if not isinstance(node.func, IRAttribute):
            raise ValueError("Expected IRAttribute for namespace call")
        if not isinstance(node.func.value, IRName):
            raise ValueError("Expected IRName for namespace call")

        namespace = self._get_module_namespace(node.func.value.id, context)
        function_name = node.func.attr

        # 查找函数签名以获取 param_overrides
        signature = self._find_function_signature(node, context)

        # 生成参数列表，应用 param_overrides
        func_args = self._render_args_with_overrides(node, context, signature)

        func_code = f"{namespace}::{function_name}"
        is_macro = (
            signature and getattr(signature, "is_macro", False) if signature else False
        )
        code = self._generate_function_call_code(func_code, func_args, is_macro)

        return EmitResult(code=code, precedence=get_operator_precedence("call"))

    def _get_param_cpp_types(
        self, node: IRCall, signature, context: CodeGenContext
    ) -> list:
        """获取函数参数的 C++ 类型列表

        Args:
            node: 调用节点
            signature: 函数签名
            context: 代码生成上下文

        Returns:
            参数 C++ 类型列表
        """
        if not signature or not hasattr(signature, "param_types"):
            return []

        cpp_types = []
        for param_type_str in signature.param_types:
            # 跳过 self 参数（方法调用）
            if param_type_str == "self" or (
                isinstance(node.func, IRAttribute) and len(cpp_types) == 0
            ):
                if isinstance(node.func, IRAttribute):
                    # 第一个参数是 self，跳过
                    continue

            # 将类型字符串转换为 C++ 类型

            try:
                type_info = parse_type_with_context(param_type_str, node=node)
                cpp_type = get_cpp_type(type_info, node)
                cpp_types.append(cpp_type)
            except:
                cpp_types.append(None)

        return cpp_types

    def _find_function_signature(self, node: IRCall, context: CodeGenContext):
        """查找函数签名

        使用类型推导阶段缓存的符号。符号查找系统会返回一个只包含匹配签名的 Symbol，
        因此可以直接使用 signatures[0]。
        """
        if not isinstance(node.func, IRAttribute):
            return None

        cached_symbol = node.func.get_extension_param("symbol")
        if cached_symbol and cached_symbol.signatures:
            # 符号查找已经匹配了签名，直接使用第一个签名
            return cached_symbol.signatures[0]

        return None

    def _render_args_with_overrides(
        self, node: IRCall, context: CodeGenContext, signature
    ) -> list[str]:
        """渲染函数参数列表，应用 param_overrides

        Args:
            node: 调用节点
            context: 代码生成上下文
            signature: 函数签名（可能包含 param_overrides）

        Returns:
            参数代码列表
        """

        generator = get_global_generator()
        args: list[str] = []

        param_overrides = getattr(signature, "param_overrides", {}) if signature else {}

        # 获取参数类型列表（用于传递期望类型）
        param_cpp_types = self._get_param_cpp_types(node, signature, context)

        # 渲染位置参数
        for i, arg in enumerate(node.args):
            # 获取该参数的期望类型
            expected_cpp_type = param_cpp_types[i] if i < len(param_cpp_types) else None

            # 创建带期望类型的上下文
            arg_context = context.create_child_context(
                expected_cpp_type=expected_cpp_type
            )
            arg_code = generator.generate_expression(arg, arg_context)

            # 应用参数覆盖
            if signature and param_overrides:
                arg_code = self._apply_param_override(
                    arg_code, i, signature, param_overrides
                )

            args.append(arg_code)

        # 渲染关键字参数
        for key, value in node.keywords:
            if key:
                value_code = generator.generate_expression(value, context)
                args.append(value_code)

        return args

    def _apply_param_override(
        self, arg_code: str, arg_index: int, signature, param_overrides: dict
    ) -> str:
        """应用参数覆盖，自动添加类型转换操作符

        Args:
            arg_code: 参数代码
            arg_index: 参数索引
            signature: 函数签名
            param_overrides: 参数覆盖字典 {参数名: 覆盖类型}

        Returns:
            可能经过转换的参数代码
        """
        if not param_overrides:
            return arg_code

        # 获取参数名（从签名的 args 列表）
        if not hasattr(signature, "args") or arg_index >= len(signature.args):
            return arg_code

        param_name = signature.args[arg_index]
        if param_name not in param_overrides:
            return arg_code

        override_type = param_overrides[param_name]

        # 如果覆盖类型是 Pointer[T]，需要取地址
        if isinstance(override_type, str) and override_type.startswith("Pointer["):
            return f"&{arg_code}"

        return arg_code

    def _render_args(self, node: IRCall, context: CodeGenContext) -> list[str]:
        """渲染函数参数列表

        迁移自IRCall._render_args方法，增加参数类型转换
        """

        generator = get_global_generator()
        args: list[str] = []

        # 获取函数签名以确定参数类型
        param_types = self._get_function_param_types(node, context)

        # 渲染位置参数
        for i, arg in enumerate(node.args):
            arg_code = generator.generate_expression(arg, context)

            # 应用参数类型转换
            if i < len(param_types):
                arg_code = self._apply_param_type_conversion(
                    arg_code, arg, param_types[i], context
                )

            args.append(arg_code)

        # 渲染关键字参数
        for key, value in node.keywords:
            if key:
                value_code = generator.generate_expression(value, context)
                # TODO: 关键字参数的类型转换需要根据参数名查找
                args.append(value_code)

        return args

    def _is_module_with_namespace(
        self, module_name: str, context: CodeGenContext
    ) -> bool:
        """检查模块是否定义了命名空间"""
        ir_module = context.ir_module
        if not ir_module:
            return False

        # 使用新的命名空间映射
        imported_namespaces = ir_module.get_extension_param(
            "imported_module_namespaces"
        )
        if imported_namespaces:
            return module_name in imported_namespaces

        return False

    def _get_module_namespace(self, module_name: str, context: CodeGenContext) -> str:
        """获取模块的命名空间"""
        ir_module = context.ir_module
        if not ir_module:
            return ""

        # 使用新的命名空间映射
        imported_namespaces = ir_module.get_extension_param(
            "imported_module_namespaces"
        )
        if imported_namespaces:
            return imported_namespaces.get(module_name, "")

        return ""

    def _is_static_member(
        self, class_name: str, method_name: str, context: CodeGenContext
    ) -> bool:
        """检查是否为静态方法调用

        通过符号表查找类和方法，检查方法是否为静态方法
        """

        # 查找类符号
        if not context.current_node:
            return False

        class_symbol = context.current_node.lookup_symbol(class_name)
        if not class_symbol or class_symbol.kind != SymbolKind.CLASS:
            return False

        # 获取类的IR节点
        class_node = class_symbol.ir_node
        if not class_node:
            return False

        # 查找方法节点
        method_node = class_node.find_symbol_ir_node(method_name)
        if method_node and hasattr(method_node, "is_static"):
            return getattr(method_node, "is_static", False)

        return False

    def _is_object_pointer_type(self, node: IRCall) -> bool:
        """检查对象是否为指针类型

        迁移自IRCall._is_object_pointer_type方法
        """
        if not isinstance(node.func, IRAttribute):
            return False

        obj_type = node.get_object_type()
        if not obj_type:
            return False

        type_name = str(obj_type.name)

        # 1. 直接检查是否是Pointer[T]格式
        if type_name.startswith("Pointer[") and type_name.endswith("]"):
            return True

        # 2. 检查类型别名是否解析为指针类型
        registry = get_global_registry()
        if type_name in registry._type_aliases:
            resolved_type = registry._type_aliases[type_name]
            if resolved_type.startswith("Pointer[") and resolved_type.endswith("]"):
                return True

        # 3. 检查类型名称中是否包含指针标识
        type_name_lower = type_name.lower()
        if "pointer" in type_name_lower or type_name.endswith("*"):
            return True

        # 4. 检查是否是泛型Pointer类型
        if obj_type.kind == TypeKind.GENERIC and obj_type.name == "Pointer":
            return True

        return False

    def _get_function_param_types(
        self, node: IRCall, context: CodeGenContext
    ) -> list[str]:
        """获取函数参数的 C++ 类型列表

        Args:
            node: 函数调用节点
            context: 代码生成上下文

        Returns:
            参数的 C++ 类型列表
        """
        # 如果是简单的函数名调用
        if isinstance(node.func, IRName):
            func_name = node.func.id
            # 在当前模块中查找函数定义
            if context.ir_module:
                for ir_node in context.ir_module.nodes:
                    if (
                        isinstance(ir_node, IRFunctionNode)
                        and ir_node.name == func_name
                    ):
                        # 获取参数类型
                        param_types = []
                        for param in ir_node.params:
                            param_cpp_type = param.get_extension_param("cpp_type")
                            if param_cpp_type:
                                param_types.append(param_cpp_type)
                        return param_types

        # 如果是方法调用或其他复杂情况，暂时返回空列表
        # TODO: 支持方法调用、导入函数等情况
        return []

    def _apply_param_type_conversion(
        self, arg_code: str, arg_node, param_cpp_type: str, context: CodeGenContext
    ) -> str:
        """应用函数参数的类型转换

        Args:
            arg_code: 参数表达式的生成代码
            arg_node: 参数表达式的 IR 节点
            param_cpp_type: 参数期望的 C++ 类型
            context: 代码生成上下文

        Returns:
            转换后的代码
        """

        # 获取实际参数的类型
        arg_cpp_type = context.get_cpp_type(arg_node)

        # 应用类型转换
        result = apply_variant_conversion(arg_code, arg_cpp_type, param_cpp_type)
        if result != arg_code:
            # 需要 mcpy 辅助函数
            context.require_include("mcpy/builtins.h")

        return result

    def _is_stack_lambda_call(self, node: IRCall, context: CodeGenContext) -> bool:
        """检查是否是栈闭包（lambda 或嵌套函数）的调用

        栈闭包应该直接调用 operator()，而不是通过 mcpy::call()

        注意：如果有默认参数且调用时参数不足，需要通过 mcpy::call() 处理

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            bool: 是否是栈闭包调用
        """
        # 方法 1：检查是否有预设标记（由 TypeReplacementPass 设置）
        if node.func.get_extension_param("is_stack_lambda_ref", False):
            # 检查是否需要使用默认参数
            if self._needs_default_params(node):
                return False  # 需要默认参数，使用 mcpy::call
            return True

        # 方法 2（回退）：基于 Python 类型和 C++ 类型判断
        # 检查 Python 类型是否是函数类型（lambda 或嵌套函数）
        func_type = node.func.get_extension_param("inferred_type")
        if not func_type or func_type.kind != TypeKind.FUNCTION:
            return False  # 不是函数类型

        # 再检查 C++ 类型判断存储模式
        # 栈模式：functor 名称（__lambda_* 或 __nested_func_*）
        # 堆模式：mc::variant
        func_cpp_type = node.func.get_extension_param("cpp_type")
        if func_cpp_type and (
            func_cpp_type.startswith("__lambda_")
            or func_cpp_type.startswith("__nested_func_")
        ):
            # 检查是否需要使用默认参数
            if self._needs_default_params(node):
                return False  # 需要默认参数，使用 mcpy::call
            return True  # 栈闭包（lambda 或嵌套函数）

        return False  # 堆闭包或其他 Callable

    def _needs_default_params(self, node: IRCall) -> bool:
        """检查调用是否需要使用默认参数

        Args:
            node: 调用节点

        Returns:
            bool: 是否需要默认参数
        """
        # 获取 lambda 的类型信息
        func_type = node.func.get_extension_param("inferred_type")
        if not func_type or not hasattr(func_type, "args"):
            return False

        # 获取 lambda 的参数数量和调用时提供的参数数量
        expected_param_count = len(func_type.args) if func_type.args else 0
        provided_param_count = len(node.args)

        # 如果提供的参数少于期望的参数，说明需要使用默认参数
        return provided_param_count < expected_param_count

    def _needs_default_params_for_nested_function(
        self, node: IRCall, context: CodeGenContext
    ) -> bool:
        """检查嵌套函数调用是否需要使用默认参数

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            bool: 是否需要默认参数
        """
        from mcpy.ir.expressions.basic import IRName
        from mcpy.ir.declarations.function import IRFunctionNode

        # 必须是直接函数名调用
        if not isinstance(node.func, IRName):
            return False

        func_name = (
            node.func.id if hasattr(node.func, "id") else getattr(node.func, "name", "")
        )

        # 查找函数节点（复用符号查找逻辑）
        symbol = None
        if hasattr(node, "get_parent_scope"):
            parent_scope = node.get_parent_scope()
            if parent_scope and hasattr(parent_scope, "lookup_symbol"):
                symbol = parent_scope.lookup_symbol(func_name)

        if not symbol and context.current_node:
            if hasattr(context.current_node, "lookup_symbol"):
                symbol = context.current_node.lookup_symbol(func_name)

        if not symbol or not symbol.ir_node:
            return False

        if not isinstance(symbol.ir_node, IRFunctionNode):
            return False

        func_node = symbol.ir_node

        # 获取函数参数列表
        params = getattr(func_node, "params", [])
        if not params:
            return False

        # 计算必需参数数量（没有默认值的参数数量）
        required_param_count = 0
        for param in params:
            if not hasattr(param, "default_value") or param.default_value is None:
                required_param_count += 1

        # 获取调用时提供的参数数量
        provided_param_count = len(node.args)

        # 如果提供的参数少于必需参数数量，或者少于总参数数量，说明需要使用默认参数
        total_param_count = len(params)
        return provided_param_count < total_param_count

    def _is_callable_variant_call(self, node: IRCall, context: CodeGenContext) -> bool:
        """检查是否是存储在 variant 中的可调用对象的调用

        适用于所有可调用对象场景：
        - Lambda 变量：`f = lambda x: x + 1; f(5)`
        - 容器中的 lambda：`funcs[0](5)`
        - 函数返回值：`get_func()(5)`
        - 成员函数返回值：`obj.get_func()(5)`
        - Callable 类型变量：`func: Callable = ...; func(5)`
        - 栈 lambda 使用默认参数：`f = lambda x=1: x; f()`

        不适用于（使用普通调用）：
        - 普通函数：`print(5)` → `print(5)`
        - C++ 可调用对象：`obj(5)` → `obj(5)` (operator() 重载)
        - 成员方法：`obj.method(5)` → `obj.method(5)`
        - 全局异步函数：`async_func()` → `struct_name{}()`

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            bool: 是否应该使用 mcpy::call() 接口
        """
        # 优先检查：全局异步函数不应该走可调用对象调用路径
        # 它们应该生成 struct_name{}() 形式的调用
        if self._is_global_async_struct_call(node, context):
            return False

        # 检查是否是简单嵌套函数（无捕获）
        # 如果不需要默认参数，不应该走可调用对象调用路径，应该生成临时对象调用
        # 如果需要默认参数，应该使用 mcpy::call 路径
        simple_functor_name = self._get_simple_nested_function_functor_name(
            node, context
        )
        if simple_functor_name:
            # 检查是否需要默认参数
            if self._needs_default_params_for_nested_function(node, context):
                # 需要默认参数，使用 mcpy::call
                return True
            else:
                # 不需要默认参数，生成临时对象调用（不走 mcpy::call 路径）
                return False

        # 特殊情况：lambda 表达式字面量
        # (lambda x: x + 1)(5)
        if isinstance(node.func, IRLambda):
            # C++ lambda 直接调用，不需要 mcpy::call()
            # extension lambda 需要通过 mcpy::call() 调用
            return node.func.usage_mode != "cpp_lambda"

        func_type = node.func.get_extension_param("inferred_type")
        func_cpp_type = node.func.get_extension_param("cpp_type")

        # 如果没有 cpp_type，尝试从上下文获取
        if not func_cpp_type and isinstance(node.func, IRName):
            func_cpp_type = context.get_cpp_type(node.func)

            # 再次尝试：从符号表获取
            if not func_cpp_type:
                symbol = node.func.lookup_symbol(node.func.id)
                if symbol and symbol.type_info:
                    func_cpp_type = get_cpp_type(symbol.type_info, node.func)

        # 如果还是没有 func_type，尝试从符号表获取
        # 这对于函数参数（如 Callable 类型的参数）很重要
        if not func_type and isinstance(node.func, IRName):
            symbol = node.func.lookup_symbol(node.func.id)
            if symbol and symbol.type_info:
                func_type = symbol.type_info

        # 检查是否是栈闭包（lambda 或嵌套函数）需要使用默认参数
        # 栈闭包的 cpp_type 是 functor 名称（__lambda_* 或 __nested_func_*）
        if (
            func_type
            and func_type.kind == TypeKind.FUNCTION
            and func_cpp_type
            and (
                func_cpp_type.startswith("__lambda_")
                or func_cpp_type.startswith("__nested_func_")
            )
            and self._needs_default_params(node)
        ):
            return True

        # 特殊处理：std::function 类型（来自 TypeVar + Callable）
        # std::function 直接调用，不需要 mcpy::call
        if func_cpp_type and "std::function" in func_cpp_type:
            return False  # 直接调用 std::function，不使用 mcpy::call

        # 检查是否是可调用 variant：
        # 利用 Python 侧的完整类型信息判断
        # 1. 有函数类型（FUNCTION 或 Callable 协议）
        # 2. cpp_type 是 mc::variant 或 const mc::variant&
        if func_type and func_cpp_type:
            # 标准化 cpp_type（去除 const 和引用）
            normalized_cpp_type = (
                func_cpp_type.replace("const ", "").replace("&", "").strip()
            )

            if normalized_cpp_type == "mc::variant":
                # 检查 Python 侧是否是函数类型
                # 1. TypeKind.FUNCTION（如 lambda）
                # 2. Callable 协议（通过名称判断，因为协议类型的 kind 是 GENERIC）
                is_function = (
                    func_type.kind == TypeKind.FUNCTION or func_type.name == "Callable"
                )
                if is_function:
                    return True

        return False

    def _get_explicit_template_args(self, node: IRCall, context: CodeGenContext):
        """获取显式模板参数列表

        对于模板函数调用，如果 C++ 无法自动推导模板参数，
        则生成显式模板参数列表。

        例如：apply<int>(f, x)

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            模板参数字符串（如 "int, int"），如果不需要则返回 None
        """
        # 只处理 IRName 函数调用（普通函数）
        if not isinstance(node.func, IRName):
            return None

        # 查找被调用函数的定义
        func_symbol = node.func.lookup_symbol(node.func.id)
        if not func_symbol or not func_symbol.ir_node:
            return None

        func_node = func_symbol.ir_node

        if not isinstance(func_node, IRFunctionNode):
            return None

        # 检查是否是当前模块的函数（通过检查 parent）
        # 内置函数或导入的函数没有 parent
        if not func_node.parent:
            return None

        # 检查是否是模板函数
        template_params = func_node.get_extension_param("template_params")
        if not template_params:
            return None  # 不是模板函数

        # 检查是否包含 Callable 参数（需要显式模板参数的标志）
        # 只有包含 Callable 参数的模板函数才需要显式模板参数
        # 其他情况 C++ 可以自动推导
        has_callable_param = False
        for param in func_node.params:
            if param.type_annotation:
                param_type = parse_type(param.type_annotation, func_node)
                if param_type and is_protocol_type(param_type, func_node):
                    has_callable_param = True
                    break

        if not has_callable_param:
            return None  # 不包含 Callable，C++ 可以自动推导

        # 推导模板参数的具体类型
        # 策略：从参数类型和返回类型推导
        template_args = {}

        # 1. 从函数参数推导
        for i, param in enumerate(func_node.params):
            if i >= len(node.args):
                break

            # 获取参数的类型注解
            param_type = (
                parse_type(param.type_annotation, func_node)
                if param.type_annotation
                else None
            )
            if not param_type:
                continue

            # 跳过 Callable 协议参数（无法从 variant 推导类型）
            # Callable 参数的 TypeVar 会从其他地方推导（如其他参数或返回类型）
            if is_protocol_type(param_type, func_node):
                continue

            # 获取实参的推导类型
            arg_type = node.args[i].get_extension_param("inferred_type")
            if not arg_type:
                continue

            # 匹配 TypeVar
            self._match_typevar(param_type, arg_type, template_args)

        # 2. 从返回类型推导
        # 优先从 context 的 expected_cpp_type 获取（赋值语句的目标类型）
        expected_cpp_type = context.expected_cpp_type
        if expected_cpp_type:
            expected_type_info = parse_type_with_context(expected_cpp_type, node)

            func_return = func_node.get_extension_param("inferred_type")
            if (
                func_return
                and hasattr(func_return, "return_type")
                and func_return.return_type
            ):
                self._match_typevar(
                    func_return.return_type, expected_type_info, template_args
                )

        # 回退：从 inferred_type 推导
        elif node.get_extension_param("inferred_type"):
            expected_return = node.get_extension_param("inferred_type")
            func_return = func_node.get_extension_param("inferred_type")
            if (
                func_return
                and hasattr(func_return, "return_type")
                and func_return.return_type
            ):
                # 只有当 expected_return 不是 TYPE_PARAM 时才匹配
                # （避免 R 匹配 R 的情况）
                if expected_return.kind != TypeKind.TYPE_PARAM:
                    self._match_typevar(
                        func_return.return_type, expected_return, template_args
                    )

        # 生成模板参数字符串
        if not template_args:
            return None

        # 识别哪些 TypeVar 可以从非 Callable 参数推导
        deducible_typevars = set()
        for i, param in enumerate(func_node.params):
            if i >= len(node.args):
                break

            param_type = (
                parse_type(param.type_annotation, func_node)
                if param.type_annotation
                else None
            )
            if param_type and not is_protocol_type(param_type, func_node):
                # 非 Callable 参数的 TypeVar 可以自动推导
                self._collect_typevars(param_type, deducible_typevars)

        # 只生成不能自动推导的 TypeVar
        cpp_args = []
        for param_name in template_params:
            if param_name in deducible_typevars:
                # 可以自动推导，跳过
                continue

            if param_name in template_args:
                type_info = template_args[param_name]
                cpp_type = get_cpp_type(type_info, node)
                if cpp_type:
                    cpp_args.append(cpp_type)
                else:
                    return None  # 无法推导，放弃
            else:
                # 不能推导的参数缺失，放弃
                return None

        # 如果没有需要显式指定的参数，返回 None
        if not cpp_args:
            return None

        return ", ".join(cpp_args)

    def _collect_typevars(self, type_info, typevars: set):
        """收集类型中的所有 TypeVar 名称

        Args:
            type_info: 类型信息
            typevars: 输出的 TypeVar 名称集合
        """
        if not type_info:
            return

        # 如果是 TypeVar，收集名称
        if type_info.kind == TypeKind.TYPE_PARAM:
            typevars.add(type_info.name)
            return

        # 递归收集泛型参数中的 TypeVar
        if hasattr(type_info, "args") and type_info.args:
            for arg in type_info.args:
                self._collect_typevars(arg, typevars)

        # 递归收集函数参数和返回类型中的 TypeVar
        if hasattr(type_info, "param_types") and type_info.param_types:
            for param_type in type_info.param_types:
                self._collect_typevars(param_type, typevars)

        if hasattr(type_info, "return_type") and type_info.return_type:
            self._collect_typevars(type_info.return_type, typevars)

    def _match_typevar(self, pattern_type, concrete_type, template_args: dict):
        """匹配类型模板，提取 TypeVar 的具体类型

        Args:
            pattern_type: 模式类型（可能包含 TypeVar）
            concrete_type: 具体类型
            template_args: 输出字典（TypeVar 名 → 具体类型）
        """
        if not pattern_type or not concrete_type:
            return

        # 如果模式是 TypeVar，记录映射
        if pattern_type.kind == TypeKind.TYPE_PARAM:
            if pattern_type.name not in template_args:
                template_args[pattern_type.name] = concrete_type
            return

        # 递归匹配泛型参数
        if hasattr(pattern_type, "args") and hasattr(concrete_type, "args"):
            if pattern_type.args and concrete_type.args:
                if len(pattern_type.args) == len(concrete_type.args):
                    for p, c in zip(pattern_type.args, concrete_type.args):
                        self._match_typevar(p, c, template_args)

    def _get_call_return_type(self, node: IRCall, context: CodeGenContext) -> str:
        """获取 mcpy::call 的返回类型模板参数

        分析调用节点的返回类型，决定是否需要添加模板参数：
        - 强类型返回：返回 "<int>"（生成 mcpy::call<int>(...)）
        - 弱类型返回：返回 ""（生成 mcpy::call(...)，默认 mc::variant）

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            str: 模板参数字符串（如 "<int>" 或 ""）
        """
        # 优先使用expected_return_cpp_type（AsyncTransformPass设置）
        expected_cpp_type = node.get_extension_param("expected_return_cpp_type")
        if expected_cpp_type:
            return f"<{expected_cpp_type}>"

        # 获取调用的返回类型
        inferred_type = node.get_extension_param("inferred_type")
        if not inferred_type:
            return ""  # 无类型信息，使用默认

        cpp_type = get_cpp_type(inferred_type, node)

        # 如果 cpp_type 是强类型（不是 mc::variant、void），则添加模板参数
        # void 表示类型推导失败，应使用默认 mc::variant
        if cpp_type and cpp_type not in ("mc::variant", "void"):
            return f"<{cpp_type}>"

        # 弱类型、未知类型或 void，使用默认（mc::variant）
        return ""

    def _get_global_async_struct_name(
        self, node: IRCall, context: CodeGenContext
    ) -> str:
        """获取全局异步函数的 struct 名称

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            如果是全局异步函数调用，返回生成的 struct 名称；否则返回空字符串
        """
        from mcpy.ir.expressions.basic import IRName
        from mcpy.ir.declarations.function import IRFunctionNode

        # 必须是直接函数名调用（不是成员调用）
        if not isinstance(node.func, IRName):
            return ""

        # 查找函数符号
        # IRName 使用 id 属性，不是 name 属性
        func_name = (
            node.func.id if hasattr(node.func, "id") else getattr(node.func, "name", "")
        )
        if not context.current_node:
            return ""

        # 检查是否是捕获的变量（嵌套函数）
        captured_vars = getattr(context.current_node, "captured_vars", None) or getattr(
            context.current_node, "closure_vars", None
        )
        if captured_vars and func_name in captured_vars:
            # 是捕获的嵌套函数，已经是对象实例
            return ""

        symbol = context.current_node.lookup_symbol(func_name)
        if not symbol or not symbol.ir_node:
            return ""

        # 必须是函数节点
        if not isinstance(symbol.ir_node, IRFunctionNode):
            return ""

        func_node = symbol.ir_node

        # 检查是否是全局函数（没有外层函数）
        parent = func_node.parent
        while parent and parent.node_type != "function":
            parent = parent.parent

        if parent and parent.node_type == "function":
            # 是嵌套函数，不是全局函数
            return ""

        # 检查是否是异步函数
        if not func_node.is_async:
            return ""

        # 生成全局异步函数的 struct 名称
        ir_module = func_node.get_ir_module()
        module_name = (
            ir_module.module_full_name
            if ir_module and ir_module.module_full_name
            else "module"
        )

        # 去除特殊字符，替换为下划线
        clean_module_name = module_name.replace(".", "_").replace("/", "_")
        return f"{clean_module_name}_{func_node.name}"

    def _is_global_async_struct_call(
        self, node: IRCall, context: CodeGenContext
    ) -> bool:
        """检查是否是调用全局异步函数 struct

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            如果是全局异步函数调用则返回 True
        """
        return bool(self._get_global_async_struct_name(node, context))

    def _get_simple_nested_function_functor_name(
        self, node: IRCall, context: CodeGenContext
    ) -> str:
        """获取简单嵌套函数（无捕获）的 functor 名称

        Args:
            node: 调用节点
            context: 代码生成上下文

        Returns:
            如果是简单嵌套函数调用，返回 functor 名称；否则返回空字符串
        """
        from mcpy.ir.expressions.basic import IRName
        from mcpy.ir.declarations.function import IRFunctionNode

        # 必须是直接函数名调用（不是成员调用）
        if not isinstance(node.func, IRName):
            return ""

        func_name = (
            node.func.id if hasattr(node.func, "id") else getattr(node.func, "name", "")
        )

        # 查找函数符号：从调用节点向上遍历，找到包含该调用的函数节点
        symbol = None

        # 方法1：从调用节点本身查找（通过父作用域）
        if hasattr(node, "get_parent_scope"):
            parent_scope = node.get_parent_scope()
            if parent_scope and hasattr(parent_scope, "lookup_symbol"):
                symbol = parent_scope.lookup_symbol(func_name)

        # 方法2：从 context.current_node 查找
        if not symbol and context.current_node:
            if hasattr(context.current_node, "lookup_symbol"):
                symbol = context.current_node.lookup_symbol(func_name)
            # 如果 current_node 有 get_parent_scope，也从父作用域查找
            if not symbol and hasattr(context.current_node, "get_parent_scope"):
                parent_scope = context.current_node.get_parent_scope()
                if parent_scope and hasattr(parent_scope, "lookup_symbol"):
                    symbol = parent_scope.lookup_symbol(func_name)

        # 方法3：从调用节点向上遍历，找到包含函数节点
        if not symbol:
            from mcpy.ir.declarations.function import IRFunctionNode

            current = node.parent
            while current:
                # 如果当前节点是函数节点，直接查找
                if isinstance(current, IRFunctionNode):
                    if hasattr(current, "lookup_symbol"):
                        symbol = current.lookup_symbol(func_name)
                        if symbol:
                            break
                # 其他节点也尝试查找
                elif hasattr(current, "lookup_symbol"):
                    symbol = current.lookup_symbol(func_name)
                    if symbol:
                        break
                # 如果当前节点有 get_parent_scope，也从父作用域查找
                if not symbol and hasattr(current, "get_parent_scope"):
                    parent_scope = current.get_parent_scope()
                    if parent_scope and isinstance(parent_scope, IRFunctionNode):
                        if hasattr(parent_scope, "lookup_symbol"):
                            symbol = parent_scope.lookup_symbol(func_name)
                            if symbol:
                                break
                current = current.parent if hasattr(current, "parent") else None
        if not symbol or not symbol.ir_node:
            return ""

        # 必须是函数节点
        if not isinstance(symbol.ir_node, IRFunctionNode):
            return ""

        func_node = symbol.ir_node

        # 检查是否是嵌套函数（不是全局函数）
        # 向上遍历查找外层函数节点
        from mcpy.ir.declarations.function import IRFunctionNode

        parent = func_node.parent
        while parent:
            if isinstance(parent, IRFunctionNode):
                # 找到了外层函数，说明是嵌套函数
                break
            if hasattr(parent, "parent"):
                parent = parent.parent
            else:
                parent = None

        if not parent or not isinstance(parent, IRFunctionNode):
            # 不是嵌套函数，是全局函数
            return ""

        # 检查是否是简单函数（无捕获）
        is_simple = func_node.get_extension_param("is_simple_non_capturing", False)
        if not is_simple:
            # 如果标记未设置，检查 captured_vars 是否为空
            captured_vars = getattr(func_node, "captured_vars", None)
            is_simple = not captured_vars or len(captured_vars) == 0

        if not is_simple:
            # 不是简单函数
            return ""

        # 获取 functor 名称
        from mcpy.codegen.emitters.nested_function.utils import get_functor_name

        return get_functor_name(func_node)

    def get_priority(self) -> int:
        """获取发射器优先级"""
        return 50  # 中等优先级，低于TemplateEmitter(40)
